﻿#ifndef __SS_ASIO_NETWORK_H__
#define __SS_ASIO_NETWORK_H__
#include "ssAsioSession.h"
#include "ssIOService.h"
#include "tools/ssIDAlloter.h"
#include "thread/ssThread.h"
//#include "../../StarSeekerBaseLib/thread/ssThreadLock.h"
#include <boost/shared_array.hpp>

//当前session管理未加锁，只能用于单个工作线程
namespace StarSeeker
{
typedef boost::shared_ptr<boost::thread> threadPtr;

class ssAsioNetWork
{
public:
	ssAsioNetWork(void);
	virtual~ssAsioNetWork(void);
	//参数配置
	void InitParam(u32 sessionCount, u32 threadCount, u32 recvBuffSize);
	//启动网络服务
	bool StartNetWork(const char *ip, const u16 port, bool isClient);
	//停止网络服务并释放内存
	void StopNetWork();
	//是否有连接(作为客户时调用)
	bool IsConnect();
	//通知ASIO关闭连接
	void DoCloseSocket(u32 sessionId, asioClose_e errTypr, i32 err);
	//通知ASIO发送数据
	void DoSendData(u32 sessionId, char* buf, u32 len);
	void DoSendDataMulti(std::vector<u32>& sessionId, char* buf, u32 len);
	void DoSendDataAll(char* buf, u32 len);
	//重新连接(作为客户端断线时调用)
	void Reconnect();
	//客户端的SessionID(作为客户时调用)
	u32 GetClientID();
	//返回连接个数
	u32 GetSessionCount();
	//返回未处理完的发送请求次数
	lint GetSendEventCount();
	//处理网络消息
	virtual void OnSessionMessage(const char* ip, u32 sessionID, u32 msgID, char* data, ssNetMsgHead* head);
protected:
	//释放所有连接
	void ClearSession();
	//通知ASIO监听,新连接进入后要重复调用
	void DoAccept();
	//通知ASIO接收数据,接收后要重复调用
	void DoReceive(ssAsioSessionPtr& ptr);
	//处理连接进入
	void HandleAccept(boost::shared_ptr<boost::asio::ip::tcp::socket> s, const boost::system::error_code& error);
	//处理连接关闭
	void HandleCloseSocket(u32 sessionId, asioClose_e origin);
	//处理发送
	void HandleSendData(u32 sessionId, boost::shared_array<char> buf, u32 len);
	void HandleSendMulti(std::vector<u32>& sessionId, boost::shared_array<char> buf, u32 len);
	void HandleSendAll(boost::shared_array<char> buf, u32 len);
	//处理接收数据后
	void HandleAfterRead(const boost::system::error_code& error, size_t bytes, u32 sessionId);
	//处理发送数据后
	void HandleAfterWrite(const boost::system::error_code& error, size_t bytes, u32 sessionId, boost::shared_array<char> buf);
	//查找session
	ssAsioSessionPtr FindSession(u32 id);
	//尝试连接,客户端调用
	bool ConnectToServer();
	//连接断开后
	virtual void OnSessionClose(u32 sessionID){};
	//连接建立后
	virtual void OnNewSession(u32 sessionID){};
protected:
	ssIOService								m_ioservice;		//io服务对象
	boost::asio::ip::tcp::endpoint			m_addr;				//地址
	boost::asio::ip::tcp::acceptor			m_acceptor;			//监听socket
	std::vector<threadPtr>					m_threads;			//网络线程
	std::map<u32, ssAsioSessionPtr>			m_sessionMap;		//连接对象
	u32										m_sessionCount;		//连接对象最大数量
	u32										m_threadCount;		//线程数量
	u32										m_recvBuffSize;		//包缓冲大小
	//ssThreadLock							m_lock;				//线程锁
private:
	ssCumulationID<u32>						m_sessionID;		//连接编号源
	bool									m_isClient;			//作为客户端
	bool									m_exiting;			//正在退出
	lint									m_sendEventCount;	//未处理完的发送事件次数
};

}
#endif
